// VerticalScrollbar.cpp : implementation file
//

#include "stdafx.h"
#include "BBSimple.h"
#include "VerticalScrollbar.h"
#include "MEMDC.H"


// CVerticalScrollbar

IMPLEMENT_DYNAMIC(CVerticalScrollbar, CStatic)

CVerticalScrollbar::CVerticalScrollbar()
{
	m_bMouseDown			= FALSE;
	m_bMouseDownArrowUp		= FALSE;
	m_bMouseDownArrowDown	= FALSE;
	m_bDragging				= FALSE;

// 	LPST_BMP_INFO lpBmpInfo;
// 
// 	lpBmpInfo = theApp.BmpInfo.GetAt(biScrl_v_uparrow);
// 	m_nSpanTop = lpBmpInfo->rtImageRect.Height();
// 
// 	lpBmpInfo = theApp.BmpInfo.GetAt(biScrl_v_downarrow);
// 	m_nSpanBottom = lpBmpInfo->rtImageRect.Height();
// 
// 	lpBmpInfo = theApp.BmpInfo.GetAt(biScrl_v_thumb);
// 	m_nThumbHeight = lpBmpInfo->rtImageRect.Height();
// 
// 	m_nThumbTop				= m_nSpanTop;
// 	m_dbThumbInterval		= 0.000000;

	m_pList					= NULL;
}

CVerticalScrollbar::~CVerticalScrollbar()
{
}


BEGIN_MESSAGE_MAP(CVerticalScrollbar, CStatic)
	ON_WM_ERASEBKGND()
	ON_WM_LBUTTONDOWN()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
	ON_WM_PAINT()
	ON_WM_TIMER()
	ON_WM_CREATE()
END_MESSAGE_MAP()


int CVerticalScrollbar::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CStatic::OnCreate(lpCreateStruct) == -1)
		return -1;

	m_nSpanTop = 26;

	//lpBmpInfo = theApp.BmpInfo.GetAt(biScrl_v_downarrow);
	m_nSpanBottom = 26;//lpBmpInfo->rtImageRect.Height();

	//lpBmpInfo = theApp.BmpInfo.GetAt(biScrl_v_thumb);
	m_nThumbHeight = 26;//lpBmpInfo->rtImageRect.Height();

	m_nThumbTop				= m_nSpanTop;
	m_dbThumbInterval		= 0.000000;

	return 0;
}
// CVerticalScrollbar message handlers
BOOL CVerticalScrollbar::OnEraseBkgnd(CDC* pDC) 
{
	return CStatic::OnEraseBkgnd(pDC);
}

void CVerticalScrollbar::OnLButtonDown(UINT nFlags, CPoint point) 
{
	SetCapture();
	CRect clientRect;
	GetClientRect(&clientRect);

	int nHeight = clientRect.Height() - m_nSpanTop;

// 	LPST_BMP_INFO lpBmpInfo;
// 
// 	lpBmpInfo = theApp.BmpInfo.GetAt(biScrl_v_uparrow);
	CRect rectUpArrow(0, 26, 0, 12);// = lpBmpInfo->rtImageRect;

//	lpBmpInfo = theApp.BmpInfo.GetAt(biScrl_v_downarrow);
	CRect rectDownArrow(0, 26, 0, 12);// = lpBmpInfo->rtImageRect;
	rectDownArrow.InflateRect(0, -nHeight, 0, nHeight);
	//lpBmpInfo = theApp.BmpInfo.GetAt(biScrl_v_thumb);
	CRect rectThumb(0, 26, 0, 12);// = lpBmpInfo->rtImageRect;
	rectThumb.InflateRect(0, -m_nThumbTop, 0, m_nThumbTop);

	if (rectThumb.PtInRect(point))
	{
		m_bMouseDown = TRUE;
	}

	if (rectDownArrow.PtInRect(point))
	{
		m_bMouseDownArrowDown = TRUE;
		SetTimer(2,250,NULL);
	}

	if (rectUpArrow.PtInRect(point))
	{
		m_bMouseDownArrowUp = TRUE;
		SetTimer(2,250,NULL);
	}

	CStatic::OnLButtonDown(nFlags, point);
}

void CVerticalScrollbar::OnLButtonUp(UINT nFlags, CPoint point) 
{
	UpdateThumbPosition();
	KillTimer(1);
	ReleaseCapture();

	BOOL bInChannel = TRUE;

	CRect clientRect;
	GetClientRect(&clientRect);
	int nHeight = clientRect.Height() - m_nSpanTop;

// 	LPST_BMP_INFO lpBmpInfo;
// 
// 	lpBmpInfo = theApp.BmpInfo.GetAt(biScrl_v_uparrow);
	CRect rectUpArrow(0, 26, 0, 12);// = lpBmpInfo->rtImageRect;

	//lpBmpInfo = theApp.BmpInfo.GetAt(biScrl_v_downarrow);
	CRect rectDownArrow(0, 26, 0, 12);// = lpBmpInfo->rtImageRect;
	rectDownArrow.InflateRect(0, -nHeight, 0, nHeight);
	//lpBmpInfo = theApp.BmpInfo.GetAt(biScrl_v_thumb);
	CRect rectThumb(0, 26, 0, 12);// = lpBmpInfo->rtImageRect;
	rectThumb.InflateRect(0, -m_nThumbTop, 0, m_nThumbTop);


	if (rectUpArrow.PtInRect(point) && m_bMouseDownArrowUp)
	{
		ScrollUp();	
		bInChannel = FALSE;
	}

	if (rectDownArrow.PtInRect(point) && m_bMouseDownArrowDown)
	{
		ScrollDown();
		bInChannel = FALSE;
	}

	if (rectThumb.PtInRect(point))
	{
		bInChannel = FALSE;
	}

	if (bInChannel && !m_bMouseDown)
	{
		if(point.y > m_nThumbTop)
		{
			PageDown();
		}
		else
		{
			PageUp();
		}
	}

	m_bMouseDown		  = FALSE;
	m_bDragging			  = FALSE;
	m_bMouseDownArrowUp   = FALSE;
	m_bMouseDownArrowDown = FALSE;

	CStatic::OnLButtonUp(nFlags, point);
}

void CVerticalScrollbar::OnMouseMove(UINT nFlags, CPoint point) 
{
	CRect clientRect;
	GetClientRect(&clientRect);

	if (m_bMouseDown)
	{
		m_nThumbTop = point.y-12/2; //-13 so mouse is in middle of thumb

		int nMax = m_pList->GetScrollLimit(SB_VERT);
		int nPos = m_pList->GetScrollPos(SB_VERT);
		int nHeight = clientRect.Height() - (m_nSpanTop+m_nSpanBottom+m_nThumbHeight);

		int nScrollTimes;
		if ((nMax==0) || (nHeight==0))
		{
			nScrollTimes = 0;
		}
		else
		{
			nScrollTimes = (m_nThumbTop-m_nSpanTop)/nMax*nMax*nMax/nHeight-nPos;
		}

		//grab the row height dynamically
		//so if the font size or type changes
		//our scroll will still work properly
		CRect itemrect;
		m_pList->GetItemRect(0,&itemrect, LVIR_BOUNDS);

		CSize size;
		size.cx = 0;
		size.cy = nScrollTimes*itemrect.Height();

		m_pList->Scroll(size);
//		m_pList->Invalidate();

		LimitThumbPosition();
		Draw();

	}

	CStatic::OnMouseMove(nFlags, point);
}

void CVerticalScrollbar::SetMouseWheel(int nVal)
{
	if (nVal<0)
	{
		m_pList->SendMessage(WM_VSCROLL, MAKELONG(SB_LINEDOWN,0),NULL);
	}
	else
	{
		m_pList->SendMessage(WM_VSCROLL, MAKELONG(SB_LINEUP,0),NULL);
	}
	UpdateThumbPosition();

}

void CVerticalScrollbar::OnPaint() 
{
	CPaintDC dc(this); 

	Draw();
}

void CVerticalScrollbar::OnTimer(UINT nIDEvent) 
{
	if (nIDEvent == 1)
	{
		if (m_bMouseDownArrowDown)
		{
			ScrollDown();
		}

		if (m_bMouseDownArrowUp)
		{
			ScrollUp();
		}
	}
	else if (nIDEvent == 2)
	{
		if (m_bMouseDownArrowDown)
		{
			KillTimer(2);
			SetTimer(1, 50, NULL);
		}

		if (m_bMouseDownArrowUp)
		{
			KillTimer(2);
			SetTimer(1, 50, NULL);
		}
	}

	CStatic::OnTimer(nIDEvent);
}

void CVerticalScrollbar::PageDown()
{
	m_pList->SendMessage(WM_VSCROLL, MAKELONG(SB_PAGEDOWN,0),NULL);
	UpdateThumbPosition();
}

void CVerticalScrollbar::PageUp()
{
	m_pList->SendMessage(WM_VSCROLL, MAKELONG(SB_PAGEUP,0),NULL);
	UpdateThumbPosition();
}

void CVerticalScrollbar::ScrollUp()
{
	m_pList->SendMessage(WM_VSCROLL, MAKELONG(SB_LINEUP,0),NULL);
	UpdateThumbPosition();
}

void CVerticalScrollbar::ScrollDown()
{
	m_pList->SendMessage(WM_VSCROLL, MAKELONG(SB_LINEDOWN,0),NULL);
	UpdateThumbPosition();
}

void CVerticalScrollbar::UpdateThumbPosition(BOOL bCheckMouseMove)
{
	if (bCheckMouseMove)
	{
		if (m_bMouseDown)
			return;
	}

	UpdateThumbPosition();
}

void CVerticalScrollbar::UpdateThumbPosition()
{
	CRect clientRect;
	GetClientRect(&clientRect);

	int nPos = m_pList->GetScrollPos(SB_VERT);
	int nMax = m_pList->GetScrollLimit(SB_VERT);
	int nHeight = clientRect.Height() - (m_nSpanTop+m_nSpanBottom+m_nThumbHeight);
	int nNewValue;
	if (nMax < 1)
	{
		m_nThumbTop = m_nSpanTop;
	}
	else
	{
		nNewValue = nHeight*nPos/nMax;
		m_nThumbTop = nNewValue+m_nSpanTop;
	}

	LimitThumbPosition();

	Draw();
}

void CVerticalScrollbar::Draw()
{
	CClientDC dc(this);
	CRect clientRect;
	GetClientRect(&clientRect);
	CMemoryDC memDC(&dc, &clientRect);
	memDC.FillSolidRect(&clientRect,  RGB(74,82,107));
	CDC bitmapDC;
	bitmapDC.CreateCompatibleDC(&dc);

	CBitmap *pBmp, *pOldBitmap;
	CRect rtImageRect;
	HBITMAP hbmpImage_uparrow;
	HBITMAP hbmpImage_downarrow;
	HBITMAP hbmpImage_span;
	HBITMAP hbmpImage_thumb;
	int nTop, nBottom;

	nTop = 0;

	CString strImage;
	strImage.Format(_T("%s\\Scrollbar\\VerticleScrollBarUpArrow.bmp"), theApp.m_strImageRoot);

	hbmpImage_uparrow = (HBITMAP)LoadImage(GetModuleHandle(NULL), strImage, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE|LR_LOADFROMFILE);
	pBmp = CBitmap::FromHandle(hbmpImage_uparrow);
	pOldBitmap = bitmapDC.SelectObject(pBmp);
	memDC.BitBlt(clientRect.left, clientRect.top+nTop, 
		12, 26, 
		&bitmapDC, 0, 0, SRCCOPY);
	bitmapDC.SelectObject(pOldBitmap);
	pOldBitmap = NULL;

	nTop += 26;

	nBottom = 0;

	//draw the down arrow of the scrollbar
	strImage.Format(_T("%s\\Scrollbar\\VerticleScrollBarDownArrow.bmp"), theApp.m_strImageRoot);
	hbmpImage_downarrow = (HBITMAP)LoadImage(GetModuleHandle(NULL), strImage, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE|LR_LOADFROMFILE);
	pBmp = CBitmap::FromHandle(hbmpImage_downarrow);
	pOldBitmap = bitmapDC.SelectObject(pBmp);
	memDC.BitBlt(clientRect.left, clientRect.bottom-nBottom-26, 
		12, 26, &bitmapDC, 0, 0, SRCCOPY);
	bitmapDC.SelectObject(pOldBitmap);
	pOldBitmap = NULL;

	nBottom += 26;

	//draw the background (span)
	strImage.Format(_T("%s\\Scrollbar\\VerticleScrollBarSpan.bmp"), theApp.m_strImageRoot);
	hbmpImage_span = (HBITMAP)LoadImage(GetModuleHandle(NULL), strImage, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE|LR_LOADFROMFILE);
	pBmp = CBitmap::FromHandle(hbmpImage_span);
	pOldBitmap = bitmapDC.SelectObject(pBmp);
	int nHeight = clientRect.Height() - nTop ;

	memDC.StretchBlt(clientRect.left, clientRect.top+nTop, 12, clientRect.Height() - (nTop + nBottom), 
		&bitmapDC, 0,0, 12, 1, SRCCOPY);

	bitmapDC.SelectObject(pOldBitmap);
	pOldBitmap = NULL;

	//If there is nothing to scroll then don't
	//show the thumb control otherwise show it
	if (m_pList->GetScrollLimit(SB_VERT) != 0)
	{
		//draw the thumb control
		strImage.Format(_T("%s\\Scrollbar\\VerticleScrollBarThumb.bmp"), theApp.m_strImageRoot);
		hbmpImage_thumb = (HBITMAP)LoadImage(GetModuleHandle(NULL), strImage, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE|LR_LOADFROMFILE);
		pBmp = CBitmap::FromHandle(hbmpImage_thumb);
		pOldBitmap = bitmapDC.SelectObject(pBmp);
		
		memDC.BitBlt(clientRect.left, clientRect.top+m_nThumbTop, 
			12, 26, &bitmapDC, 0, 0, SRCCOPY);
		bitmapDC.SelectObject(pOldBitmap);
		pOldBitmap = NULL;
		//DeleteObject(hbmpImage_thumb);
	}

// 	DeleteObject(hbmpImage_downarrow);
// 	DeleteObject(hbmpImage_uparrow);
// 	DeleteObject(hbmpImage_span);
}

void CVerticalScrollbar::LimitThumbPosition()
{
	CRect clientRect;
	GetClientRect(&clientRect);

	int nHeight = clientRect.Height();

	if (m_nThumbTop+m_nThumbHeight> (nHeight - m_nSpanBottom))
	{
		m_nThumbTop = nHeight - (m_nThumbHeight+m_nSpanBottom);
	}

	if (m_nThumbTop < (clientRect.top+m_nSpanTop))
	{
		m_nThumbTop = clientRect.top+m_nSpanTop;
	}
}



